/***************************************************************************//**
 * @file
 * @brief See @ref platform_common and @ref unix_gcc_config for documentation.
 *******************************************************************************
 * # License
 * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
 *******************************************************************************
 *
 * The licensor of this software is Silicon Laboratories Inc. Your use of this
 * software is governed by the terms of Silicon Labs Master Software License
 * Agreement (MSLA) available at
 * www.silabs.com/about-us/legal/master-software-license-agreement. This
 * software is distributed to you in Source Code format and is governed by the
 * sections of the MSLA applicable to Source Code.
 *
 ******************************************************************************/
/** @addtogroup unix_gcc_config
 * @brief Compiler and Platform specific definitions and typedefs for the
 *  the Unix GCC compiler.
 *
 * @note ATOMIC and interrupt manipulation macros are defined to have no
 * affect.
 *
 * @note gcc.h should be included first in all source files by setting the
 *  preprocessor macro PLATFORM_HEADER to point to it.  gcc.h automatically
 *  includes platform-common.h.
 *
 * See @ref platform_common for common documentation.
 *
 * See gcc.h for source code.
 *@{
 */

#ifndef __GCC_H__
#define __GCC_H__

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

/** \name Master Variable Types
 * These are a set of typedefs to make the size of all variable declarations
 * explicitly known.
 */
//@{

/**
 * @brief A typedef to make the size of the variable explicitly known.
 */

#ifndef EMBER_USE_WINDOWS_BOOLEAN // prevent duplicate definition of boolean
typedef bool boolean; /*To ease adoption of bool instead of boolean.*/
#endif

typedef unsigned char int8u;
typedef signed char int8s;
typedef unsigned short int16u;
typedef signed short int16s;
typedef unsigned int int32u;
typedef signed int int32s;
typedef unsigned long long int64u;
typedef signed long long int64s;
typedef unsigned long PointerType;
//@} \\END MASTER VARIABLE TYPES

/**
 * @brief Denotes that this platform supports 64-bit data-types.
 */
#define HAL_HAS_INT64

/**
 * @brief Use the Master Program Memory Declarations from platform-common.h
 */
#define _HAL_USE_COMMON_PGM_

/**
 * @brief A definition stating what the endianess of the platform is.
 */
#ifdef DOXYGEN_SHOULD_SKIP_THIS
#define BIGENDIAN_CPU false
#else
#if defined(__i386__)
#define BIGENDIAN_CPU  false
#elif defined(__ARM7__)
#define BIGENDIAN_CPU  false
#elif defined(__x86_64__)
#define BIGENDIAN_CPU  false
#elif defined(__arm__)
#if defined(__BIG_ENDIAN)
#define BIGENDIAN_CPU  true
#else
#define BIGENDIAN_CPU  false
#endif
#elif defined(__LITTLE_ENDIAN__)
#define BIGENDIAN_CPU  false
#elif defined(__BIG_ENDIAN__)
#define BIGENDIAN_CPU  true
#elif defined(__APPLE__)
#define BIGENDIAN_CPU  true
#elif defined(__mips__)
#if defined(__BIG_ENDIAN)
#define BIGENDIAN_CPU  true
#else
#define BIGENDIAN_CPU  false
#endif
#else
#error endianess not defined
#endif
#endif

#ifndef DOXYGEN_SHOULD_SKIP_THIS
#define NO_STRIPPING
#define EEPROM

// Always include stdio.h and assert.h if running under Unix so that they
// can be used when debugging.
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>

#define NOP()
#define DECLARE_INTERRUPT_STATE
#define DECLARE_INTERRUPT_STATE_LITE
#define DISABLE_INTERRUPTS()              do {} while (0)
#define DISABLE_INTERRUPTS_LITE()         do {} while (0)
#define RESTORE_INTERRUPTS()              do {} while (0)
#define RESTORE_INTERRUPTS_LITE()         do {} while (0)
#define INTERRUPTS_ON()                   do {} while (0)
#define INTERRUPTS_OFF()                  do {} while (0)
#if defined(EMBER_TEST)
#define INTERRUPTS_ARE_OFF()              (true)
#else
#define INTERRUPTS_ARE_OFF()              (false)
#endif
#define ATOMIC(blah)                      { blah }
#define ATOMIC_LITE(blah)                 { blah }
#define HANDLE_PENDING_INTERRUPTS()       do {} while (0)

#define LOG_MESSAGE_DUMP

#define UNUSED                            __attribute__ ((unused))
#define SIGNED_ENUM

// think different
#ifdef __APPLE__
#define __unix__
#endif

#ifdef WIN32
// undefine this here too
// See bug EMSTACK-2808
#if !defined(IMAGE_BUILDER)
#define __attribute__(foo)
#endif
#endif

#if defined(EMBER_TEST)
#define MAIN_FUNCTION_PARAMETERS 			void
#define MAIN_FUNCTION_ARGUMENTS				//... ...

// Called by application main loops to let the simulator simulate.
// Not used on real hardware.
void simulatedTimePasses(void);             // time moves forward 4ms
void simulatedTimePassesUs(uint32_t us);      // time moves forward us microseconds

// This moves time forward for the minimum of:
//   - timeToNextAppEvent milliseconds
//   - time until the next stack event fires
//   - time until next serial character is read or written
// This is used to allow time to pass more efficiently - if there is nothing
// to do it can move the clock forward by a large amount.
void simulatedTimePassesMs(uint32_t timeToNextAppEvent);

#else	//main 传入参数
#define MAIN_FUNCTION_PARAMETERS 					int argc, char* argv[]
#define MAIN_FUNCTION_ARGUMENTS  					argc, argv
#define MAIN_FUNCTION_HAS_STANDARD_ARGUMENTS		//... ...

// Stub for code not running in simulation.
#define simulatedTimePasses()
#define simulatedTimePassesUs(x)
#define simulatedTimePassesMs(x)

#endif

// Called by the serial code when it wants to block.
void simulatedSerialTimePasses(void);

#endif //DOXYGEN_SHOULD_SKIP_THIS

/**
 * @brief Provide a portable way to align data.
 */
#define ALIGNMENT(__alignmentBytes) \
  __attribute__ ((aligned(__alignmentBytes)))

/**
 * @brief Provide a portable way to specify a symbol as weak
 */
#define WEAK(__symbol) \
  __attribute__ ((weak)) __symbol

/**
 * @brief Provide a portable way to specify a compile time assert
 */
#define STATIC_ASSERT(__condition, __errorstr) \
  _Static_assert(__condition, __errorstr)

/** \name Watchdog Prototypes
 * Define the watchdog macro and internal function to simply be
 * stubs to satisfy those programs that have no HAL (i.e. scripted tests)
 * and those that want to reference real HAL functions (simulation binaries
 * and Unix host applications) we define both halResetWatchdog() and
 * halInternalResetWatchdog().  The former is used by most of the scripted
 * tests while the latter is used by simulation and real host applications.
 */
//@{

/** @brief Watchdog stub prototype.
 */
void halInternalResetWatchDog(void);

#if defined(EMBER_SCRIPTED_TEST)
#define halResetWatchdog()
#else
#define halResetWatchdog() \
  halInternalResetWatchDog()
#endif
//@} //end of Watchdog Prototypes

/**
 * Include string.h for the C Standard Library memory routines used in
 * platform-common.
 */
#include <string.h>

/**
 * @brief Use the Divide and Modulus Operations from platform-common.h
 */
#define _HAL_USE_COMMON_DIVMOD_

/**
 * @brief Include platform-common.h last to pick up defaults and common definitions.
 */
#define PLATCOMMONOKTOINCLUDE
#include "hal/micro/generic/compiler/platform-common.h"
#undef PLATCOMMONOKTOINCLUDE

#endif //__GCC_H__

/**@}END addtogroup
 */
